package com.ysx.server.recommend.service.impl;
import java.math.BigDecimal;
import com.google.common.collect.Lists;
import java.time.LocalDateTime;

import com.ysx.server.mapper.GoodsMapper;
import com.ysx.server.mapper.OrderDetailMapper;
import com.ysx.server.mapper.OrderMapper;
import com.ysx.server.pojo.entity.Goods;
import com.ysx.server.pojo.entity.OrderDetail;
import com.ysx.server.pojo.entity.Orders;
import com.ysx.server.pojo.vo.GoodsVO;
import com.ysx.server.recommend.core.ItemCF;
import com.ysx.server.recommend.dto.ProductDTO;
import com.ysx.server.recommend.dto.RelateDTO;
import com.ysx.server.recommend.service.RecommendService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
@Slf4j
public class RecommendServiceImpl implements RecommendService {
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;

    /**
     * 获取商品表所有商品id
     *
     * @return
     */
    @Override
    public List<ProductDTO> getProductData() {
        List<ProductDTO> productDTOList = new ArrayList<>();
        List<Goods> goodsList = null;
        //获得所有上架商品
        goodsList = goodsMapper.getAll();
        List<Long> goodIds = goodsList.stream().map(Goods::getId).toList();
        for (Long goodId : goodIds) {
            ProductDTO productDTO = new ProductDTO();
            productDTO.setProductId(goodId);
            productDTOList.add(productDTO);
        }
        return productDTOList;
    }

    /**
     * 根据所有用户购买商品的记录进行数据手机
     *
     * @return List<RelateDTO>
     */
    @Override
    public List<RelateDTO> getRelateData() {
        List<RelateDTO> relateDTOList = new ArrayList<>();
        // 获取所有订单以及订单关联商品的集合
        //获取所有钉单
        List<Orders> orders = orderMapper.getAll();
        //获取订单id集合
        List<Long> orderIds = orders.stream().map(Orders::getOrderId).toList();
        if (orderIds.isEmpty()) {
            return Collections.emptyList();
        }
        //根据订单id得到订单-商品关联集合
        List<OrderDetail> orderItems=new ArrayList<>();
        for(Long orderId:orderIds){
            orderItems.add(orderDetailMapper.selectByOrderIds(orderId));
        }
        Map<Long, List<OrderDetail>> listMap = orderItems.stream()
                .collect(Collectors.groupingBy(OrderDetail::getOrderId));
        Map<String, List<OrderDetail>> goodsListMap = orderItems.stream()
                .collect(Collectors.groupingBy(OrderDetail::getGoodsName));
        // 遍历订单，生成预处理数据
        for (Orders order : orders) {
            Long orderId = order.getOrderId();
            // 遍历订单商品
            for (OrderDetail orderDetail : listMap.getOrDefault(orderId, Collections.emptyList())) {
                Long goodsId = orderDetail.getGoodsId();
                RelateDTO relateDTO = new RelateDTO();
                relateDTO.setUserId(order.getUserId());
                relateDTO.setProductId(goodsId);
                relateDTO.setProductName(orderDetail.getGoodsName());
                // 通过计算商品购买次数，来建立相似度
                List<OrderDetail> list = goodsListMap.getOrDefault(orderDetail.getGoodsName(), Collections.emptyList());
                int sum = list.stream().mapToInt(OrderDetail::getGoodsCount).sum();
                relateDTO.setIndex(sum);
                relateDTOList.add(relateDTO);
            }
        }
        return relateDTOList;
    }

    @Override
    public List<Goods> recommendGoods(Long userId, Integer num) {
        List<Goods> recommendGoods = new ArrayList<>();
        // 获取商品数据
        List<RelateDTO> relateDTOList = getRelateData();
        // 执行算法，返回推荐商品id
        List<Long> recommendIdLists = ItemCF.recommend(userId, num, relateDTOList);
        if (CollectionUtils.isNotEmpty(recommendIdLists)) {
            Map<Long, Integer> integerMap = IntStream.range(0, recommendIdLists.size()).boxed().collect(Collectors.toMap(recommendIdLists::get, i -> i));
            // 获取商品DTO（这里的过滤是防止商品表该id商品已下架或删除）
            List<ProductDTO> productDTOList = getProductData().stream().filter(e -> recommendIdLists.contains(e.getProductId())).toList();
            // 获取商品ids
            List<Long> goodIds = productDTOList.stream().map(ProductDTO::getProductId).toList();
            if (CollectionUtils.isNotEmpty(goodIds)) {
                // 获取所有推荐商品
                for (Long id:goodIds){
                    Goods goods = goodsMapper.getById(id);
                    recommendGoods.add(goods);
                }
                recommendGoods.sort(Comparator.comparingInt(o -> integerMap.get(o.getId())));
            }
        } else {
            // 用户未购买过商品时，基于用户点击量推荐
            Map<Long, Long> collect = relateDTOList.stream().collect(Collectors.groupingBy(RelateDTO::getProductId, Collectors.counting()));
            LinkedHashSet<Map.Entry<Long, Long>> linkedHashSet = collect.entrySet().stream().sorted((o1, o2) -> Math.toIntExact(o2.getValue() - o1.getValue()))
                    .collect(Collectors.toCollection(LinkedHashSet::new));
            List<Long> goodIds = linkedHashSet.stream().map(Map.Entry::getKey).distinct().limit(num).toList();
            Map<Long, Integer> integerMap = IntStream.range(0, goodIds.size()).boxed().collect(Collectors.toMap(goodIds::get, i -> i));
            if (CollectionUtils.isNotEmpty(goodIds)) {
                // 获取所有推荐商品
                for (Long id:goodIds){
                    Goods goods = goodsMapper.getById(id);
                    recommendGoods.add(goods);
                }
                recommendGoods.sort(Comparator.comparingLong(o -> integerMap.get(o.getId())));
            }
        }
        return recommendGoods.stream().limit(num).toList();
    }
}
